import { _decorator, Asset, Component, dragonBones, Node, sp } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 循环次数
 */
export enum ANIM_TIMES {
    FOREVER = -1,
    ONCE = 1
}

/**
 * 动画类型
 */
export enum ANIM_TYPE {
    DRAGON_BONES = "DragonBones",
    SPINE = "Spine"
}


/**
 * 动画组件
 * 
 * 控制角色的状态与动画切换
 */
@ccclass('AnimAction')
export class AnimAction extends Component {

    public animCtrl: dragonBones.ArmatureDisplay | sp.Skeleton = null!;

    // 空闲动画名称
    private restName: string = "rest"

    // 当前动画名称
    private animName: string = null;

    /**
     * 动画初始化
     * @param animNode 动画节点
     * @param animType 动画类型
     * @param resource 骨骼资源
     * @param restName 空闲动画
     */
    public init(animNode: Node, animType: ANIM_TYPE, resource: Asset[], restName: string = "rest"): void {
        this.restName = restName
        if (animType === ANIM_TYPE.DRAGON_BONES) {
            const animCtrl = animNode.addComponent(dragonBones.ArmatureDisplay)
            resource.forEach(asset => {
                if (asset instanceof dragonBones.DragonBonesAsset) {
                    animCtrl.dragonAsset = asset
                } else if (asset instanceof dragonBones.DragonBonesAtlasAsset) {
                    animCtrl.dragonAtlasAsset = asset
                }
            })
            animCtrl.armatureName = JSON.parse(animCtrl.dragonAsset?.dragonBonesJson!).armature[0].name;
            this.animCtrl = animCtrl;
        } else {
            const animCtrl = animNode.addComponent(sp.Skeleton)
            resource.forEach(asset => {
                if (asset instanceof sp.SkeletonData) {
                    animCtrl.skeletonData = asset
                }
            })
            this.animCtrl = animCtrl;
        }

    }

    /**
     * 
     * @param animName 动画名称
     * @param times 次数
     * @param completeFunc 动画完成时回调函数
     * @returns 
     */
    public setState(animName: string, times: ANIM_TIMES = ANIM_TIMES.FOREVER, completeFunc?: Function): Promise<number> {
        return new Promise((resolve) => {
            // 如果当前状态和期望状态是同一个，则不需要改变
            if (this.animName == animName) {
                return;
            }
            this.animName = animName

            // 播放动画，结束后播放rest
            let animCtrl = this.animCtrl;
            if (animCtrl instanceof dragonBones.ArmatureDisplay) {
                animCtrl.playAnimation(animName, times)
                if (times == ANIM_TIMES.ONCE) {
                    animCtrl.once(dragonBones.EventObject.COMPLETE, () => {
                        animCtrl.playAnimation(this.restName, ANIM_TIMES.FOREVER)
                        completeFunc && completeFunc()
                        resolve(1)
                    }, this)
                }
            } else {
                animCtrl.setAnimation(0, animName, times == ANIM_TIMES.FOREVER)
                if (times == ANIM_TIMES.ONCE) {
                    animCtrl.setCompleteListener((trackEntry: sp.spine.TrackEntry) => {
                        let spineAnimationName: any = trackEntry.animation.name ? trackEntry.animation.name : "";
                        if (animName === spineAnimationName) {
                            animCtrl.setAnimation(0, this.restName, true)
                            completeFunc && completeFunc()
                            resolve(1)
                        }
                    })
                }
            }
        })
    }


}